import json
from typing import Union
from typing import List
from apis import api_routes
from flask import abort, g, request, jsonify
from models.users.roles import Roles
from models.users.users import Users
from security.decoration import certification
from sqlalchemy import text
from security.security import encode_jwt
from public.local import datetime_type
from security.security import decode_jwt
from public.contexts import context_logs


@api_routes.route("/login", methods=["POST"])
def func_users_login_post_api():
    """
    用户登录操作,  完成API开发
    http://127.0.0.1:8080/api/login
    Content-Type=application/json
    methods=["POST"]
    {
    "account"  string  ****    人员工号
    "password" string  ****    密码
    }
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}  参数没到位
        {'status': 4000, 'msg': "不存在此账户"}
        {'status': 4001, 'msg': "账户密码不正确"}
        {'status': 4002, 'msg': "此账户禁止登录"}
        {'status': 200, 'data': "data"}
    ---
    tags:
      - 用户管理
    """
    request_json = request.get_json()
    account = request_json.get("account")
    password = request_json.get("password")

    if not all([account, password]):
        abort(400)

    sql = """
        SELECT 
            users.id, users.account, users.name, users.phone, users.framework, 
            users.password, coalesce(to_char(users.time,'YYYY-MM-DD'), null), users.enable, 
            coalesce(to_char(users.modify,'YYYY-MM-DD'), null), roles.id, roles.role, roles.describe, roles.sidebars
        FROM users INNER JOIN roles on users.role_id = roles.id AND users.account = :account
    """
    user: Union[tuple, None] = g.session.execute(text(sql), {"account": account}).fetchone()

    if user is None:
        return jsonify({'status': 4000, 'msg': "不存在此账户"})
    if user and password != user[5]:
        return jsonify({'status': 4001, 'msg': "账户密码不正确"})
    if user and (password == user[5] and not user[7]):
        return jsonify({'status': 4002, 'msg': "此账户禁止登录"})
    token = encode_jwt({"user_id": user[0]})

    data = {
        'status': 200, 'token': token, "user_id": user[0], "account": user[1],
        "name": user[2], "phone": user[3], "sidebars": "sidebar", "framework": user[4],
        "time": user[6], "modify": user[8], "role_id": user[9], "role": user[10], "describe": user[11]
    }

    log_pram: dict = {
        "account": account
    }
    context_logs(name="登录MES系统", obsolescence=None, data=str(log_pram))
    g.session.commit()
    return jsonify(data)


@api_routes.route("/user/getUserInfo", methods=["GET"])
@certification(auth=True, role=None)
def func_user_info_get_api():
    """
    查询自己账户信息, 前端需要带token过来， 完成API开发
    http://127.0.0.1:8080/api/user/getUserInfo
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}
    ---
    tags:
      - 用户管理
    """
    user_id: int = decode_jwt(g.token)["user_id"]
    user: Users = g.session.query(Users).filter(Users.id == user_id).first()
    role: Roles = g.session.query(Roles).filter(Roles.id == user.role_id).first()

    user_json = json.loads(user.__repr__())
    role_db = json.loads(role.__repr__())
    del role_db["sidebars"]

    return jsonify({'status': 200, 'user': user_json, "role": role_db})


@api_routes.route("/register", methods=["POST"])
@certification(auth=True, role=None)
def func_user_register_post_api():
    """
    添加新的用户, 只有管理员才可以添加新的用户, 完成API开发
    http://127.0.0.1:8080/api/register
    Content-Type=application/json
    methods=["POST"]
    {
    "account"   string  ****    人员工号
    "name"      string  ****    人员名称
    "phone"     string          人员电话
    "framework" string  ****    人员组织架构
    "password"  string  ****    密码
    "role_id"   int     ****    角色id
    "enable"    int(1或者0) ****   是否可以登录
    }
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}
        {'status': 403, 'msg': "token无效或者未登录或没有权限"}
        {'status': 4000, 'msg': "已经存在此用户"}
        {'status': 200, 'msg': "添加账户成功", }
    ---
    tags:
      - 用户管理
    """
    request_json = request.get_json()
    account = request_json.get("account")
    name = request_json.get("name")
    phone = request_json.get("phone")
    framework = request_json.get("framework")
    password = request_json.get("password")
    role_id = request_json.get("role_id")
    enable = request_json.get("enable")

    if not all([framework, name, account, password, role_id]) or int(enable) not in [0, 1]:
        abort(400)
    user: Users = g.session.query(Users).filter(Users.account == account).first()
    if user:
        return jsonify({'status': 4000, 'msg': "已经存在此用户"})
    role: Roles = g.session.query(Roles).filter(Roles.id == role_id).first()
    if role is None:
        return jsonify({'status': 4001, 'msg': "role_id 没找到对应角色"})

    user_init: Users = Users(
        account=account, name=name, phone=phone,
        framework=framework, password=password,role_id=role_id,
        time=datetime_type(), enable=enable, modify=datetime_type()
    )
    g.session.add(user_init)

    context_logs(name="添加新的账户人员", obsolescence=None, data=user_init.__repr__())

    g.session.commit()
    return jsonify({'status': 200, 'msg': "添加账户成功"})


@api_routes.route("/users", methods=["GET"])
@certification(auth=True, role=None)
def func_user_list_get_api():
    """
    按照条件查询用户, 完成API开发
    组合方式:
    /api/users?index=1&size=10                      全部分页查询
    /api/users?index=1&size=10&enable=1             全部查询可以登录账户，enable==0查询不可以登录账户
    /api/users?index=1&size=10&enable=1&account=ad  全部查询可以登录账户且账户里面包含ad
    /api/users?index=1&size=10&account=ad           全部查询账户里面包含ad字符

    "index": 第几页, "size": 每页数据多少, "page": 总共多少页面, "count": 一共多少数据

    "user_id": 账户ID, "account": 账户名, "name": 用户名, "phone": 电话,
    "framework": 人员组织架构, "time": 创建时间, "modify": 最后修改时间, "role": 角色, "describe": 角色描述


    http://127.0.0.1:8080/api/users
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    {
    "index"     int      ****  第几页，默认为1
    "size"      int      ****  每页数据多少, 默认每页10条数据
    "enable"    int            可选择，过滤是否可以登录账户
    "account"   string         可选择，模糊查询
    }
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}
    ---
    tags:
      - 用户管理
    """
    index = request.args.get("index", default=1, type=int)
    size = request.args.get("size", default=10, type=int)
    enable = request.args.get("enable", default=None, type=int)
    account = request.args.get("account", default=None, type=str)

    if enable is not None and enable == 1:
        enable = 't'
    elif enable is not None and enable == 0:
        enable = 'f'
    elif enable is not None and enable not in [0, 1]:
        abort(400)

    sql_count = """
        SELECT
            COALESCE(COUNT(users.id), null)
        FROM users INNER JOIN roles on users.role_id = roles.id {}
    """
    sql_data = """
        SELECT 
            users.id, users.account, users.name, users.phone, users.framework, 
            users.password, coalesce(to_char(users.time,'YYYY-MM-DD'), null), 
            users.enable, coalesce(to_char(users.modify,'YYYY-MM-DD'), null), roles.id, roles.role, roles.describe
        FROM users INNER JOIN roles on users.role_id = roles.id {} ORDER BY users.id LIMIT :arg1 OFFSET :arg2
    """

    if enable is not None and account is None:
        sql_count = sql_count.format("WHERE users.enable = :enable")
        sql_data = sql_data.format("WHERE users.enable = :enable")
    elif enable is not None and account is not None:
        sql_count = sql_count.format("WHERE users.enable = :enable AND users.account LIKE '%{}%'".format(account))
        sql_data = sql_data.format("WHERE users.enable = :enable AND users.account LIKE '%{}%'".format(account))
    elif enable is None and account is not None:
        sql_count = sql_count.format("WHERE users.account LIKE '%{}%'".format(account))
        sql_data = sql_data.format("WHERE users.account LIKE '%{}%'".format(account))
    else:
        sql_count = sql_count.format("")
        sql_data = sql_data.format("")

    count: int = g.session.execute(text(sql_count), {"enable": enable}).fetchone()[0]
    resp, page = [], int(count / size) if count / size == int(count / size) else int(count / size) + 1

    arg2: int = (index - 1) * size
    data: list[tuple] = g.session.execute(text(sql_data), {"enable": enable, "arg1": size, "arg2": arg2}).fetchall()

    for index, itr in enumerate(data):
        temp: int = 1 if itr[7] else 0
        resp.append({
            "user_id": itr[0], "account": itr[1], "name": itr[2], "phone": itr[3], "framework": itr[4], "password": itr[5],
            "time": itr[6], "enable": temp, "modify": itr[8], "role_id": itr[9], "role": itr[10], "describe": itr[11]
        })

    return jsonify({'status': 200, 'data': resp, "index": index, "size": size, "page": page, "count": count})


@api_routes.route("/users", methods=["PUT"])
@certification(auth=True, role=None)
def func_user_put_api():
    """
    修改用户信息API, 除了"user_id" 必须传递， API 开发完成
    其他可传递，有传递则更新对应数据，没有则不更新数据, PHONE 字段前端做校验
    普通用户不可以修改内容， 自己账户可以修改自己内容，admin权限可以修改别的账户内容
    http://127.0.0.1:8080/api/users
    Content-Type=application/json
    methods=["PUT"]
    {
    "user_id"   int     ***  数据库用户ID
    "account"   string      人员工号
    "name"      string      人员名称
    "phone"     string      人员电话
    "framework" string      人员组织架构
    "password"  string      密码
    "role_id"   int         角色id
    "enable"    int(1或者0)  是否可以登录
    }
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}
        {'status': 4000, 'msg': "不存在此用户"}
        {'status': 4001, 'msg': "admin 账户不能修改账户名"}
        {'status': 4002, 'msg': "admin 账户必须可登录状态"}
        {'status': 4003, 'msg': "账户名已存在"}
        {'status': 4004, 'msg': "没有对应角色ID"}
        {'status': 200, 'msg': "修改账户成功"}
    ---
    tags:
      - 用户管理
    """
    request_json = request.get_json()
    user_id = request_json.get("user_id")
    name = request_json.get("name")
    phone = request_json.get("phone")
    account = request_json.get("account")
    framework = request_json.get("framework")
    password = request_json.get("password")
    role_id = request_json.get("role_id")
    enable = request_json.get("enable")

    if user_id is None or len(str(user_id).strip()) == 0:
        abort(400)

    # 此时已经登录状态中, 先判断是否跟token一个用户
    # token_user_id: int = decode_jwt(g.token)["user_id"]

    # 查询需要修改账户
    user1: Union[Users, None] = g.session.query(Users).filter(Users.id == user_id).first()
    if user_id is None:
        return jsonify({'status': 4000, 'msg': "不存在此用户"})

    if user1.account == "admin" and account != "admin":
        return jsonify({'status': 4001, 'msg': "admin 账户不能修改账户名"})
    if user1.account == "admin" and enable is not None and int(enable) != 1:
        return jsonify({'status': 4002, 'msg': "admin 账户必须可登录状态"})

    context_logs(name="更新账户人员", obsolescence=user1.__repr__(), data=json.dumps(request_json))

    if user1.account != account:
        user3: Users = g.session.query(Users).filter(Users.account == account).first()
        if user3 is not None:
            return jsonify({'status': 4003, 'msg': "账户名已存在"})
        else:
            user1.account = account
    if role_id is not None and int(role_id) != user1.role_id:
        role2: Roles = g.session.query(Roles).filter(Roles.id == role_id).first()
        if role2 is None:
            g.session.rollback()
            return jsonify({'status': 4004, 'msg': "没有对应角色ID"})
        else:
            user1.role_id = role_id

    if enable is not None and int(enable) in [0, 1]:
        user1.enable = True if int(enable) == 1 else False

    user1.name = name if name is not None and len(str(name)) > 0 else user1.name
    phone = phone if phone is not None else user1.phone
    if phone == '':
        user1.phone = None
    else:
        user1.phone = phone

    user1.framework = framework if framework is not None and len(str(framework)) > 0 else user1.framework
    user1.password = password if password is not None and len(str(password)) > 0 else user1.password

    user1.modify = datetime_type()

    g.session.commit()
    return jsonify({'status': 200, 'msg': "修改账户成功"})


@api_routes.route("/users", methods=["DELETE"])
@certification(auth=True, role=None)
def func_user_delete_api():
    """
    用户退出登录，前端只要传递token 就行，后端只做日志，前端记得删除日志， API开发完成
    http://127.0.0.1:8080/users
    Content-Type=application/x-www-form-urlencoded
    methods=["DELETE"]
    {
    }
    :return:
        {'status': 200, 'msg': "退出账户成功", }
    ---
    tags:
      - 用户管理
    """
    token_user_id: int = decode_jwt(g.token)["user_id"]
    user: Users = g.session.query(Users).filter(Users.id == token_user_id).first()
    path = request.path
    method = request.method

    g.session.commit()
    return jsonify({'status': 200, 'msg': "退出账户成功"})


@api_routes.route("/users/all", methods=["GET"])
@certification(auth=True, role=None)
def func_user_all_get_api():
    """
    获取全部用户，没有做分页， API开发完成
    http://127.0.0.1:8080/api/users/all
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    {
    }
    :return:
        {'status': 200, 'msg': "退出账户成功", }
    ---
    tags:
      - 用户管理
    """
    resp: list = []
    users: List[Users] = g.session.query(Users).order_by(Users.id).all()
    for user in users:
        resp.append({
            "user_id": user.id,
            "name": user.name,
            "account": user.account
        })
    return jsonify({'status': 200, 'data': resp})
